package com.trippin.DB.entities;

import java.io.IOException;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.jdo.annotations.Column;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.beoui.geocell.annotations.Latitude;
import com.beoui.geocell.annotations.Longitude;
import com.google.appengine.api.datastore.Key;
import com.google.gson.annotations.Expose;

@PersistenceCapable
public class ScheduledAttractionEntity implements TrippinEntity, Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;
	
	@Persistent
	@Expose
	private long id;
	
	@Persistent
	@Longitude
	@Expose
	private double longitude;

	@Persistent
	@Latitude
	@Column
	@Expose
	private double latitude;
	
	@Persistent
	@Expose
	private String title;
	
	@Persistent
	@Expose
	private String type;
	
	@Persistent
	@Expose
	private Long createdBy;
	
	@Persistent
	@Expose
	private Date createdOn;
	
	@Persistent
	@Expose
	private Long attrId;
	
	@Persistent
	@Expose
	private Date startTime;
	
	@Persistent
	@Expose
	private Date endTime;
	
	@Persistent
	@Expose
	private Set<Long> attendees;
	
	@Persistent
	private Set<Long> attendeesPluses;
	
	@Persistent
	@Expose
	private long pluses;
	
	@Persistent
	private Set<Long> attendeesMinuses;
	
	@Persistent
	@Expose
	private long minuses;
	
	//TODO:maybe add "comments" class/entity with user and comment, and maybe likes too

	public ScheduledAttractionEntity(long creatorId, long attrId, 
			String title, String type, Date startDate, Duration duration, double lat, double lon) throws IOException {
		this.attrId = attrId;
		this.title = title;
		this.type = type;
		this.startTime = new Date(startDate.getTime());
		this.endTime = createEndDateTime(startDate, duration);
		this.createdBy = creatorId;
		this.pluses = 0;
		this.minuses = 0;
		this.createdOn = new Date();
		
		this.latitude = lat;
		this.longitude = lon;
		
		this.attendees = new HashSet<Long>();
		this.attendeesPluses = new HashSet<Long>();
		this.attendeesMinuses = new HashSet<Long>();		
	}
		
	private Date createEndDateTime(Date startDate, Duration duration) throws IOException {
		if(duration == null) {
			 return new Date(startDate.getTime());
		}
		
		if((duration.getHours() < 0) || (duration.getMinutes() < 0)) {
			throw new IOException("duration fields must be non negative");
		}
		Calendar cal = Calendar.getInstance();
		  cal.setTime(new Date(startDate.getTime()));
		  cal.add(Calendar.HOUR_OF_DAY, duration.getHours());
		  cal.add(Calendar.MINUTE, duration.getMinutes());
		  
		  return new Date(cal.getTime().getTime());
	}

	public Key getKey() {
		return key;
	}

	public long getId() {
		if(id < 0)
			id = key.getId();
		return id;
	}

	public void setId() {
		id = key.getId();
	}
	
	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLatitude() {
		return latitude;
	}
	
	public long getcreatedBy() {
		return createdBy;
	}
	
	public Date getCreatedOn() {
		return createdOn;
	}

	public long getAttrId() {
		return attrId;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public Set<Long> getAttendees() {
		return attendees;
	}
	
	public void addAttendee(long userId) {
		attendees.add(userId);
	}
	
	public void removeAttendee(long userId) {
		attendees.remove((Long)userId);
	}


	public long getPluses() {
		return pluses;
	}


	public void addPlus(long userId) {
		if(!attendeesPluses.contains(userId)) {
			if(attendeesMinuses.contains(userId)) {
				--this.minuses;
				attendeesMinuses.remove(userId);
			}
			else {
				++this.pluses;
				attendeesPluses.add(userId);
			}
		}
	}

	public Set<Long> getAttendeesPluses() {
		return attendeesPluses;
	}

	public long getMinuses() {
		return minuses;
	}


	public void addMinus(long userId) {
		if(!attendeesMinuses.contains(userId)) {
			if(attendeesPluses.contains(userId)) {
				--this.pluses;
				attendeesPluses.remove(userId);
			}
			else {
				++this.minuses;
				attendeesMinuses.add(userId);
			}
		}
	}
	

	public Set<Long> getAttendeesMinuses() {
		return attendeesMinuses;
	}


	public String getTitle() {
		return title;
	}


	public void setTitle(String title) {
		this.title = title;
	}
	
	public String getType() {
		return type;
	}


	public void setType(String type) {
		this.type = type;
	}
	
	
	@Override
	public boolean equals(Object obj) {
		if(this == obj)
			return true;
		if(!(obj instanceof ScheduledAttractionEntity))
			return false;
		
		ScheduledAttractionEntity sae = (ScheduledAttractionEntity)obj;
		if(sae.getId() != this.getId()) {
			return false;
		}
		return true;
	}
	
}
